package query.evaluator;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import main.ISpecificPath;
import model.Balise;
import model.Document;
import query.model.UserQuery;
import database.SQLHelper;

/**
 * The {@link QueryEvaluator} evaluates the relevent {@link Balise}
 * found by this application with the relevent {@link Balise} given
 * in the result file : qrel.xml
 */
public class QueryEvaluator
{
  /** The query. */
  private UserQuery query;
  
  /** The relevent balises. */
  private List<Balise> releventBalisesFromModel;

  /**
   * Instantiates a new query comparator.
   *
   * @param releventBalises the relevent balises
   * @param query the query
   */
  public QueryEvaluator(List<Balise> releventBalises, UserQuery query)
  {
    this.releventBalisesFromModel = releventBalises;
    this.query = query;
  }

  /**
   * Tries to compare a result from a query with our program with the result
   * files given for analysis.
   */
  public void compare()
  {
    File qrelsFolder = new File(ISpecificPath.QRELS_PATH);
    File[] listFiles = qrelsFolder.listFiles();
    for (File file : listFiles)
    {
      String string = query.getQueryName() + ".txt";
      String name = file.getName().replace("qrel", "");
      if (name.equals(string))
      {
        List<String> relevantBalisesFromFile = getReleventBaliseFromResultFile(file);
        System.out.println("Query "+query.getQueryName()+" : ");
        computeRappelAndPrecision(relevantBalisesFromFile);
      }
    }
  }
  
  /**
   * Find number of relevent balises find.
   *
   * @param balisesFromResultFile the balises from result file
   * @return the double
   */
  private void computeRappelAndPrecision(List<String> balisesFromResultFile)
  {
    double avgPrecisionNumerator = 0.0;
    double avgPrecisionDenominator = 1.0;
    for (int baliseNumber = 1; baliseNumber < releventBalisesFromModel.size(); baliseNumber++)
    {
      Balise balise = releventBalisesFromModel.get(baliseNumber);
      String upperCase = balise.getUniqueID().toUpperCase();
      if(balisesFromResultFile.contains(upperCase))
      {
        System.out.println("Balise en commun : "+balise.getChemin()+balise.getNom()+"["+balise.getBaliseNumber()+"]");
        avgPrecisionNumerator += avgPrecisionDenominator / baliseNumber;
        avgPrecisionDenominator++;
      }
    }
    double avgPrecision = avgPrecisionNumerator / avgPrecisionDenominator;
    
    System.out.println("Precision = " + new DecimalFormat("#.##").format(avgPrecision * 100) + " %");
  }

  /**
   * Compare query with result file.
   *
   * @param file the file
   * @return the list
   */
  private List<String> getReleventBaliseFromResultFile(File file)
  {
    List<String> balises = new ArrayList<>();
    Map<String, Document> documentsInDatabaseAsMap = SQLHelper.getDocumentsInDatabaseAsMap();

    try
    {
      BufferedReader br = new BufferedReader(new FileReader(file));
      String line;
      while ((line = br.readLine()) != null)
      {
        String[] splitted = line.split("\\s+");
        String docPath = splitted[0];
        String balisePath = splitted[1];
        String usefulness = splitted[2];
        
        // If the third cell is == 0, the line is not relevant
        if(!usefulness.equals("0"))
        {
          String docName = docPath.substring(11, docPath.length());
          Document doc = documentsInDatabaseAsMap.get(docName);
          if(doc == null)
          {
            System.out.println("Warning !! A document was not found in the database, the evaluation will be altered");
          }
          else
          {          
            int lastIndexOfSlash = balisePath.lastIndexOf("/");
            String baliseNameWithId = balisePath.substring(lastIndexOfSlash+1, balisePath.length());
            String[] baliseNameAndId = baliseNameWithId.split("\\[");
            String baliseName = baliseNameAndId[0];
            String baliseId = baliseNameAndId[1].substring(0, baliseNameAndId[1].length() - 1);
            
            String chemin = balisePath.substring(0, lastIndexOfSlash + 1);
            
            Balise b = new Balise(baliseName, chemin, doc, Integer.valueOf(baliseId));
            balises.add(b.getUniqueID());
          }
        }
      }
      br.close();
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
    return balises;
  }

}
